#include <string.h>
#include <iostream>

using std::cout;
using std::endl;

class String
{
public:
    String();
    String(const char *pstr);
    String(const String &rhs);
    String &operator=(const String &rhs);
    //获取字符串的长度
    size_t size() const;
    //获取底层字符串
    const char *c_str() const;
    int getRefCount() const;
    ~String();

    friend std::ostream &operator<<(std::ostream &os, const String &rhs);
private:
    char *_pstr;
};

std::ostream &operator<<(std::ostream &os, const String &rhs)
{
    if(rhs._pstr)
    {
        os << rhs._pstr;
    }
    return os;
}

String::String()
: _pstr(new char[5]() + 4)
{
    cout << "String()" << endl;
    *(int *)(_pstr - 4) = 1;
}

String::String(const char *pstr)
: _pstr(new char[strlen(pstr) + 5]() + 4)
{
    /* _pstr = new char[strlen(pstr) + 5](); */
    /* _pstr = _pstr + 4; */
    cout <<"String(const char *)" << endl;
    strcpy(_pstr, pstr);
    *(int *)(_pstr - 4) = 1;
}

String::String(const String &rhs)
: _pstr(rhs._pstr)
{
    cout << "String(const String &)" << endl;
    ++*(int *)(_pstr - 4);
}

//s3 = s1
String &String::operator=(const String &rhs)
{
    cout << "String &operator=(const String &)" << endl;
    if(this != &rhs)//1、自赋值
    {
        //2、释放左操作数
#if 0
        int &cnt = *(int *)(_pstr - 4);//2.1、获取引用计数
        --cnt;//2.2、将引用计数-1
        if(cnt == 0)//2.3、如果引用计数为0，那么需要销毁空间
        {
            delete [] (_pstr - 4);//2.4、销毁空间
        }
#endif
        if(0 == --*(int *)(_pstr - 4))
        {
            delete [] (_pstr - 4);
        }


        //3、浅拷贝
        _pstr = rhs._pstr;
        ++*(int *)(_pstr - 4);
    }

    return *this;//4、返回*this
}

//获取字符串的长度
size_t String::size() const
{
    return strlen(_pstr);
}

//获取底层字符串
const char *String::c_str() const
{
    return _pstr;
}

int String::getRefCount() const
{
    return *(int *)(_pstr - 4);
}

String::~String()
{
    cout << "~String()" << endl;
    if(0 == --*(int *)(_pstr - 4))
    {
        delete [] (_pstr - 4);
    }
}

void test()
{
    String s1("hello");
    cout << "s1 = " << s1 << endl;
    cout << "s1.getRefCount() = " << s1.getRefCount() << endl;
    printf("&s1 = %p\n", s1.c_str());

    cout << endl;
    String s2 = s1;
    cout << "s1 = " << s1 << endl;
    cout << "s2 = " << s2 << endl;
    cout << "s1.getRefCount() = " << s1.getRefCount() << endl;
    cout << "s2.getRefCount() = " << s2.getRefCount() << endl;
    printf("&s1 = %p\n", s1.c_str());
    printf("&s2 = %p\n", s2.c_str());

    cout << endl;
    String s3("wangdao");
    cout << "s3 = " << s3 << endl;
    cout << "s3.getRefCount() = " << s3.getRefCount() << endl;
    printf("&s3 = %p\n", s3.c_str());

    cout << endl << "执行s3 = s1" << endl;
    s3 = s1;
    cout << "s1 = " << s1 << endl;
    cout << "s2 = " << s2 << endl;
    cout << "s3 = " << s3 << endl;
    cout << "s1.getRefCount() = " << s1.getRefCount() << endl;
    cout << "s2.getRefCount() = " << s2.getRefCount() << endl;
    cout << "s3.getRefCount() = " << s3.getRefCount() << endl;
    printf("&s1 = %p\n", s1.c_str());
    printf("&s2 = %p\n", s2.c_str());
    printf("&s3 = %p\n", s3.c_str());
}

int main(int argc, char *argv[])
{
    test();
    return 0;
}

